Release 10.1A: OpenEdge Development:
ProDataSets
Special support for change conflicts
Because the ProDataSet with its independent
FILLand save operations necessarily relies on an optimistic locking strategy, you need to consider what behavior you want in the event of a conflict with another change made since the ProDataSet was filled from its Data-Source. Progress supports a number of options to give you automated support for almost any circumstance.The first decision you need to make is whether a conflict with another change should be overwritten by the current ProDataSet’s change, or rejected when Progress detects a conflict.
In some cases, you might not care whether a record has been changed by another user since it was read. Although this is certainly not typical or recommended, for some non-transactional tables that contain fields that can safely be changed independently of one another (possibly address information, for example), you might not want to reject a change if the record has been changed elsewhere. There is a
PREFER-DATASETlogical attribute for the Data-Source to support this option. (In the very first release of 10.0A, this attribute was calledIGNORE-CURRENT-MODIFIED, and this name is still supported for compatibility, though the new name is preferred for being a clearer description of the behavior wanted.) The attribute is false by default. IfPREFER-DATASETis false for the table’s Data-Source, then Progress makes the comparison between the before-table row in the database and the corresponding data-source fields before applying the change, and if there is any conflict then the change is rejected and theERRORattribute set. IfPREFER-DATASETis true, this check is not made. The ProDataSet row changes are written to the Data-Source without regard to any other changes made to the same row. As noted previously, only the database fields that are present in the ProDataSet temp-table, either implicitly or by being mapped to a field with a different name, can be compared.You also may want to apply changes and resolve conflicts on a field by field basis. This is somewhat more expensive than either applying or rejecting all changes, but minimizes the overwriting of either your changes or another user’s changes when a conflict occurs. There is a
MERGE-BY-FIELDlogical attribute on the Data-Source to specify this preference. This attribute is true by default. It gives you the ability to define whether a change is wholly rejected if there are any conflicting changes, even to different fields than the ones the ProDataSet is changing.If it is false, then if another user has changed a record, the ProDataSet changes are either entirely accepted or entirely rejected, depending on the setting of
PREFER-DATASET. If it is true, then Progress “blends” the two sets of changes where possible, if they are to different fields. If it is true, then changes are applied field by field only for modified fields, and there is no conflict unless the same field has been modified both by the current update and by another transaction. A logicalDATA-SOURCE-MODIFIEDattribute on the temp-table buffer is set toTRUEif any field changes by another transaction are detected, regardless of whether they result in a conflict and error or not. Note that it is somewhat slower to haveMERGE-BY-FIELDset to true, so it can be set to false to improve performance where a field-by-field check is really not necessary, in addition to cases where it is not wanted because of the application logic.Here are the details of how changes are applied in the face of these attributes. In this description, “current changes” refers to modifies and deletes that are part of a ProDataSet the procedure is doing a
SAVE-ROW-CHANGESon (the “current ProDataSet”). Obviously create operations do not need to check for conflicting field values. “Other changes” refers to changes made to the fields in the same rows by another user or procedure since the current ProDataSet was filled, which will be detectable by comparing the database buffers with the before-tables in the current ProDataSet.If
MERGE-BY-FIELDis false, then these are the actions:
- If
PREFER-DATASETis true, then the modified or deleted row is updated or deleted without regard to whether there were other changes. In the case of a modify, all fields in the current ProDataSet row are copied to the database buffer, whether they were changed in the current ProDataSet or not. In the case of a delete, the database record is simply deleted.- If
PREFER-DATASETis false (the default), then Progress compares the ProDataSet before-table with the database buffers. If there are any other changes, then the current change is rejected and Progress sets theERRORattribute. If the action was a delete, the row is not deleted from the database or the current ProDataSet. Progress also sets theDATA-SOURCE-MODIFIEDattribute on the row. It buffer-copies the entire database buffer back to the current ProDataSet’s after-table row, to allow the changes to be seen back on the client.If
MERGE-BY-FIELDis true (the default), then rather than doing a wholesale buffer-copy in one direction or the other, Progress does a field by field compare of the two buffers. In this case:
- This is the action if
PREFER-DATASETis true:- Otherwise, for a modify:
- If the field has not been changed in the current ProDataSet, then nothing is copied. This means that a change made by another user to a field that wasn’t changed in the current ProDataSet won’t be overwritten by the current change.
- If the field has been changed in the current ProDataSet, it is copied to the database field. There is no check of whether there were other changes.
- These are the actions if
PREFER-DATASETis false:
- If the operation is a delete, and there are no other changes to the row, then the database record is deleted.
- If the operation is a delete, and there are other changes to the row, then the delete fails, Progress buffer-copies the entire database record into the ProDataSet buffer, and sets the
ERRORandDATA-SOURCE-MODIFIEDattributes.- Otherwise, for a Modify:
- If the field was changed in the current ProDataSet and not by other changes, then it is copied to the database.
- If the field was not changed in the current ProDataSet, and also not by other changes, then nothing is copied.
- If the field was changed in the current ProDataSet, and also by other changes, then Progress checks whether the other change was the same as the current ProDataSet change. If this is the case, then there is no conflict. Nothing is copied, because the current ProDataSet value is already in the database, and there is no error. Otherwise, if the changed values are different, Progress buffer-copies that one field from the database record back into the ProDataSet buffer, and sets the
ERRORandDATA-SOURCE-MODIFIEDflags. The current ProDataSet changes are not applied to the database, but the field by field comparison continues so that only those fields changed by other changes overwrite the current ProDataSet changes.- If the field was not changed in the current ProDataSet, but was changed by other changes, then the other change is copied into the ProDataSet buffer, and Progress sets the
DATA-SOURCE-MODIFIEDflag. This is not anERROR, however.The net result of all this, when
PREFER-DATASETis false andMERGE-BY-FIELDis true, is that a modified row in the current ProDataSet is rejected in its entirety and causes anERRORonly when one or more of the same fields have been changed by another user. Otherwise changed fields in the current ProDataSet row are successfully written to the database. Changes made by others are copied to the ProDataSet buffer to be returned to the client, and theCHANGEDflag is set.This may all sound complicated, but in effect it means that Progress “does the right thing” based on whether you want the new change or the old one to take precedence, and whether you want to apply changes field by field or as a whole. Table 6–1 summarizes the results.
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |